package com.jrtc.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jrtc.base.config.constants.Constants;
import com.jrtc.base.config.constants.PublicConstants;
import com.jrtc.base.entity.bo.*;
import com.jrtc.base.entity.vo.*;
import com.jrtc.base.util.*;
import com.jrtc.dao.*;
import com.jrtc.base.entity.vo.DoctorLoginVo;
import com.jrtc.service.DoctorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 * 医生表(Doctor)表服务实现类
 *
 * @author makejava
 * @since 2022-03-21 17:34:12
 */
@Service("doctorService")
public class DoctorServiceImpl implements DoctorService
{

    @Resource
    private DoctorDao doctorDao;
    @Autowired
    private RedisUtil redisUtil;
    @Resource
    private DepartmentDao departmentDao;
    @Resource
    private MinioUtil minioUtil;
    @Resource
    private PatientAppointmentDao patientAppointmentDao;
    @Resource
    private ExerciseprescriptionDao exerciseprescriptionDao;
    @Resource
    private PatientExerciseprescriptionDao patientExerciseprescriptionDao;
    @Resource
    private DiseaseDao diseaseDao;
    @Resource
    private PublicVideoDao publicVideoDao;
    @Resource
    private RoleDao roleDao;

    /**
     * 通过ID查询单条数据
     *
     * @param doctorId 主键
     * @return 实例对象
     */
    @Override
    public Doctor queryById(Integer doctorId) {
        return this.doctorDao.queryById(doctorId);
    }

    /**
     * 查询多条数据
     *
     * @param offset 查询起始位置
     * @param limit 查询条数
     * @return 对象列表
     */
    @Override
    public List<Doctor> queryAllByLimit(int offset, int limit) {
        return this.doctorDao.queryAllByLimit(offset, limit);
    }

    @Override
    public IPage<Doctor> queryDoctorList(Doctor doctor)
    {
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<Doctor> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(doctor.getPageNo(), doctor.getPageSize());
        IPage<Doctor> doctorPage = this.doctorDao.queryDoctorList(page, doctor);
        return doctorPage;
    }
    /**
     * 新增数据
     *
     * @param doctor 实例对象
     * @return 实例对象
     */
    @Override
    public Doctor insert(Doctor doctor) {
        this.doctorDao.insert(doctor);
        return doctor;
    }

    /**
     * 修改数据
     *
     * @param doctor 实例对象
     * @return 实例对象
     */
    @Override
    public Doctor update(Doctor doctor) {
        this.doctorDao.update(doctor);
        return this.queryById(doctor.getDoctorId());
    }

    /**
     * 通过主键删除数据
     *
     * @param doctorId 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer doctorId) {
        return this.doctorDao.deleteById(doctorId) > 0;
    }

    @Override
    public Doctor login(DoctorLoginVo doctorLogin)
    {
        Doctor doctor = new Doctor();
        doctor.setPhone(doctorLogin.getPhone());
        try {
            doctor.setPassword(KeyUtils.desEncrypt(doctorLogin.getPassword(), null).toLowerCase());
        } catch (Exception e){
            System.out.println(e);
        }

        Doctor doctorDB = this.doctorDao.login(doctor);
        if (doctorDB == null)
        {
            return null;
        }
        Collection<String> keys = redisUtil.keys(Constants.DOCTOR_LOGIN_TOKEN_KEY.getValue() + doctorLogin.getPhone() + "*");
        if (keys != null && keys.size() > 0)
        {
            for (String key : keys)
                redisUtil.del(key);
        }
        String token = IdUtils.fastUUID();
//        doctorLogin.setToken(token);
        doctorDB.setToken(token);
//        redisUtil.set(Constants.DOCTOR_LOGIN_TOKEN_KEY.getValue() + doctorLogin.getPhone() + token, JSON.toJSON(doctorLogin), 3 * 24 * 60 * 60);
        redisUtil.set(Constants.DOCTOR_LOGIN_TOKEN_KEY.getValue() + token, JSON.toJSON(doctorDB), 3 * 24 * 60 * 60);
        return doctorDB;
    }

    //医生退出登录
    @Override
    public boolean logOut(String token) {
        boolean key = redisUtil.hasKey(Constants.DOCTOR_LOGIN_TOKEN_KEY.getValue() + token);
        if (key) {
            redisUtil.del(Constants.DOCTOR_LOGIN_TOKEN_KEY.getValue() + token);
            return true;
        }
        return false;
    }

    /**
     * 根据token获取医生信息
     * */
    @Override
    public Doctor getLoginDoctor(HttpServletRequest request) throws Exception {
        String token = request.getHeader("token");
        if (token != null && !token.equals("")){
            Object object = redisUtil.get(Constants.DOCTOR_LOGIN_TOKEN_KEY.getValue() + token);
            if (object != null){
                ObjectMapper objectMapper = new ObjectMapper();
                Doctor doctor = objectMapper.convertValue(object, Doctor.class);

//                JSONObject json = JSONObject.fromObject(object);
//                Doctor doctor = (Doctor)JSONObject.toBean(json, Doctor.class);

                return doctor;
            }
            else {
                throw new Exception("登录已过期");
            }
        }
        else {
            throw new Exception("没有获取到token");
        }
    }

    /**
     * 新增医生信息
     * */
    @Override
    public int insertDoctor(Doctor doctor) throws Exception {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Date date = new Date();
        //医生注册（手机号、密码、确认密码）不能为空
        if (doctor.getPhone() != null && !doctor.getPhone().equals("") &&
                doctor.getPassword() != null && !doctor.getPassword().equals("") &&
                doctor.getTmpPassword() != null && !doctor.getTmpPassword().equals("")){

            String password = KeyUtils.desEncrypt(doctor.getPassword(), null);
            String tmpPassword = KeyUtils.desEncrypt(doctor.getTmpPassword(), null);

            //对比两次密码是否一致
            if (password.equals(tmpPassword)){
                doctor.setPassword(password);
            }
            else {
                throw new Exception("两次密码输入不一致");
            }

            doctor.setRegisterTime(date);
            if (doctor.getBirthday() != null && !doctor.getBirthday().equals("")){
                int ageByBirthday = AgeUtil.getAgeByBirthday(doctor.getBirthday().toString());
                doctor.setAge(ageByBirthday);
            }
            else {
                throw new Exception("生日不能为空");
            }

//            Department department = departmentDao.selectDepartmentByDepartmentName(departmentName);
//
//            doctor.setDepartmentId(department.getDepartmentId());

            doctor.setRegisterTime(date);

            if (doctor.getUploadFileVoList() != null && doctor.getUploadFileVoList().size() > 0){
                for (UploadFileVo uploadFileVo : doctor.getUploadFileVoList()) {
                    //医生职业照片/文件上传路径
                    if (uploadFileVo.getType().equals(PublicConstants.UniversalEnum.Profession.getValue())){
                        doctor.setUrl(uploadFileVo.getUploadFile());
                    }
                    //医生头像
                    else if (uploadFileVo.getType().equals(PublicConstants.UniversalEnum.Avatar.getValue())){
                        doctor.setDoctorPhoto(uploadFileVo.getUploadFile());
                    }
                }
            }

            int i = doctorDao.insertDoctor(doctor);
            if (i > 0){
                return i;
            }
            else {
                throw new Exception("新增失败");
            }
        }
        else {
            throw new Exception("缺少必要参数");
        }
    }

    /**
     * 医院就诊挂号医生信息
     * */
    @Override
    public ReserveDoctorVo selectDoctorById(Integer doctorId) throws Exception {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE");
        if (doctorId != null && doctorId != 0){
            Doctor doctor = doctorDao.selectDoctorById(doctorId);
            if (doctor != null){
                ReserveDoctorVo reserveDoctorVo = new ReserveDoctorVo();
                reserveDoctorVo.setDoctorName(doctor.getDoctorName());
                reserveDoctorVo.setProfessional(doctor.getProfessional());
                reserveDoctorVo.setDoctorRating(doctor.getDoctorRating());
                reserveDoctorVo.setAffiliatedHospital(doctor.getAffiliatedHospital());

                ArrayList<String> timeList = DateUtil.getDayList();
                List<RegisteredVo> registeredVoList = new ArrayList<>();
                for (String time : timeList) {
                    List<PatientAppointment> patientAppointments = patientAppointmentDao.selectPatientAppointmentByAppointmentTime(time);
                    RegisteredVo registeredVo = new RegisteredVo();
                    registeredVo.setDate(time);

                    try {
                        Date parse = format.parse(time);
                        String week = dateFormat.format(parse);
                        registeredVo.setWeek(week);
                    } catch (Exception e){
                        throw new Exception("日期转换错误");
                    }

                    if (patientAppointments.size() >= 20){
                        registeredVo.setWhetherRegistered("false");
                    }
                    else {
                        registeredVo.setWhetherRegistered("true");
                    }

                    registeredVo.setPeopleNumber(patientAppointments.size());
                    registeredVo.setRemainingNumber(20 - patientAppointments.size());
                    registeredVoList.add(registeredVo);
                }
                reserveDoctorVo.setRegisteredVoList(registeredVoList);
                return reserveDoctorVo;
            }
            else {
                throw new Exception("未查到医生数据");
            }
        }
        else {
            throw new Exception("缺少必要参数");
        }
    }

    /**
     * 医生信息及他的运动处方
     * */
    @Override
    public DoctorInformationVo selectDoctorInformationVo(Integer doctorId, InformationVo informationVo) throws Exception {
        if (doctorId != null && doctorId != 0){
            Doctor doctor = doctorDao.selectDoctorById(doctorId);
            if (doctor != null){
                DoctorInformationVo doctorInformationVo = new DoctorInformationVo();
                doctorInformationVo.setDoctorId(doctor.getDoctorId());
                doctorInformationVo.setDoctorName(doctor.getDoctorName());
                doctorInformationVo.setDoctorPhoto(doctor.getDoctorPhoto());
                if (doctor.getDepartmentId() != null && doctor.getDepartmentId() != 0){
                    Department department = departmentDao.selectDepartmentById(doctor.getDepartmentId());
                    if (department != null){
                        doctorInformationVo.setDepartmentName(department.getDepartmentName());
                    }
                }
                doctorInformationVo.setDoctorRating(doctor.getDoctorRating());
                doctorInformationVo.setAffiliatedHospital(doctor.getAffiliatedHospital());
                doctorInformationVo.setBedoctorYears(doctor.getBedoctorYears());
                doctorInformationVo.setCapability(doctor.getCapability());
                List<Disease> diseases = diseaseDao.selectDiseaseList();

                List<Exerciseprescription> exerciseprescriptionList = exerciseprescriptionDao.selectExerciseprescriptions(informationVo);
                if (diseases != null && exerciseprescriptionList != null){
                    List<ClassificationVo> classificationVos = new ArrayList<>();
                    List<ClassificationVo> classificationVoList = new ArrayList<>();
                    for (Disease disease : diseases) {
                        ClassificationVo classificationVo = new ClassificationVo();
                        ClassificationVo other = new ClassificationVo();
                        List<DoctorExercisePrescriptionVo> doctorExercisePrescriptionVoList = new ArrayList<>();
                        List<DoctorExercisePrescriptionVo> otherList = new ArrayList<>();
                        for (Exerciseprescription exerciseprescription : exerciseprescriptionList) {
                            if (disease.getDiseaseId() == exerciseprescription.getDiseaseId()){
                                DoctorExercisePrescriptionVo doctorExercisePrescriptionVo = new DoctorExercisePrescriptionVo();
                                doctorExercisePrescriptionVo.setPrescriptionId(exerciseprescription.getPrescriptionId());
                                doctorExercisePrescriptionVo.setPrescriptionName(exerciseprescription.getPrescriptionName());
                                doctorExercisePrescriptionVo.setExerciseCourse(exerciseprescription.getExerciseCourse());
                                doctorExercisePrescriptionVo.setExerciseStrength(exerciseprescription.getExerciseLevel());
                                doctorExercisePrescriptionVo.setExerciseTime(exerciseprescription.getExerciseTime());
                                doctorExercisePrescriptionVo.setPrice(exerciseprescription.getPrice());
                                doctorExercisePrescriptionVo.setMemberVIP(exerciseprescription.getMemberVIP());

                                List<PatientExerciseprescription> patientExerciseprescriptionList = patientExerciseprescriptionDao.patientCollectCount(exerciseprescription.getPrescriptionId());
                                if (patientExerciseprescriptionList == null){
                                    doctorExercisePrescriptionVo.setCount(0);
                                }
                                else {
                                    doctorExercisePrescriptionVo.setCount(patientExerciseprescriptionList.size());
                                }

                                doctorExercisePrescriptionVo.setExercisePictureURL(exerciseprescription.getExercisePictureUrl());

                                List<PublicVideo> publicVideos = publicVideoDao.selectPrescriptionvideo(exerciseprescription.getPrescriptionId());
                                if (publicVideos != null && publicVideos.size() > 0){
                                    List<String> prescriptionVideoURL = new ArrayList<>();

                                    for (PublicVideo publicVideo : publicVideos) {
                                        prescriptionVideoURL.add(publicVideo.getPrescriptionVideoUrl());
                                    }

                                    doctorExercisePrescriptionVo.setPrescriptionVideoURL(prescriptionVideoURL);
                                }

                                doctorExercisePrescriptionVo.setDoctorName(doctor.getDoctorName());
                                doctorExercisePrescriptionVo.setDoctorProfessional(doctor.getProfessional());

                                if (exerciseprescription.getDoctorId() == doctorId){
                                    doctorExercisePrescriptionVoList.add(doctorExercisePrescriptionVo);
                                }
                                else {
                                    otherList.add(doctorExercisePrescriptionVo);
                                }
                            }
                        }

                        if (doctorExercisePrescriptionVoList != null && doctorExercisePrescriptionVoList.size() > 0){
                            classificationVo.setClassificationVoName("我的运动处方");
                            classificationVo.setDiseaseId(disease.getDiseaseId());
                            classificationVo.setDiseaseName(disease.getDiseaseName());
                            classificationVo.setDoctorExercisePrescriptionVoList(doctorExercisePrescriptionVoList);
                            classificationVos.add(classificationVo);
                        }
                        if (otherList != null && otherList.size() > 0){
                            other.setClassificationVoName("其他运动处方");
                            other.setDiseaseId(disease.getDiseaseId());
                            other.setDiseaseName(disease.getDiseaseName());
                            other.setDoctorExercisePrescriptionVoList(otherList);
                            classificationVoList.add(other);
                        }
                    }

                    doctorInformationVo.setClassificationVoList(classificationVos);
                    doctorInformationVo.setOtherList(classificationVoList);

                }
                return doctorInformationVo;
            }
            else {
                throw new Exception("未查到医生信息");
            }
        }
        else {
            throw new Exception("缺少必要参数");
        }
    }

    /**
     * 医生注册文件上传
     * */
    @Override
    public List<String> uploadFile(List<MultipartFile> fileList, String type) throws Exception {
        if (fileList.size() > 0){
            String source = "doctor";
            String business;

            //医生职业照片/文件
            if (type.equals(PublicConstants.UniversalEnum.Profession.getValue())){
                business = "profession";
            }
            //医生头像
            else if (type.equals(PublicConstants.UniversalEnum.Avatar.getValue())){
                business = "avatar";
            }
            else {
                throw new Exception("文件/图片类型不明确");
            }

            List<String> uploadFileList = new ArrayList<>();
            for (MultipartFile multipartFile : fileList) {
                String uploadFile;
                try {
                    uploadFile = minioUtil.uploadFile(multipartFile, source, business);
                } catch (Exception e){
                    throw new Exception("文件上传失败");
                }

                uploadFileList.add(uploadFile);
            }
            return uploadFileList;
        }
        else {
            throw new Exception("没有接收到文件");
        }
    }

    @Override
    public List<String> puploadFile(List<MultipartFile> fileList) throws Exception {
        if (fileList.size() > 0){

            List<String> uploadFileList = new ArrayList<>();
            for (MultipartFile multipartFile : fileList) {
                String uploadFile;
                try {
                    uploadFile = minioUtil.uploadFile(multipartFile, "finge", "fuck");
                } catch (Exception e){
                    throw new Exception("文件上传失败");
                }

                uploadFileList.add(uploadFile);
            }
            return uploadFileList;
        }
        else {
            throw new Exception("没有接收到文件");
        }
    }

    /**
     * 医生信息列表
     * */
    @Override
    public List<Doctor> doctorNameList() {
        List<Doctor> doctors = doctorDao.doctorNameList();
        return doctors;
    }

    /**
     * 医生添加患者运动处方
     * */
    @Override
    public int insertPrescription(Integer doctorId, Integer id, Integer prescriptionId) throws Exception {
        PatientExerciseprescription patientExerciseprescription = new PatientExerciseprescription();
        patientExerciseprescription.setPatientId(id);
        patientExerciseprescription.setPrescriptionId(prescriptionId);

        Exerciseprescription exerciseprescription = exerciseprescriptionDao.selectExerciseprescription(prescriptionId, null);
        if (exerciseprescription == null){
            throw new Exception("未查到对应运动处方");
        }

        patientExerciseprescription.setPrescriptionName(exerciseprescription.getPrescriptionName());
        patientExerciseprescription.setIsfavourite("false");
        patientExerciseprescription.setDoctorId(doctorId);
        int i = patientExerciseprescriptionDao.insertPatientExerciseprescription(patientExerciseprescription);
        return i;
    }

    /**
     * 账号设置
     * */
    @Override
    public Doctor accountSettings(Doctor doctor) {
        Department department = departmentDao.queryById(doctor.getDepartmentId());
        if (department != null){
            doctor.setDepartment(department.getDepartmentName());
        }

        Role role = roleDao.queryById(doctor.getRoleId());
        if (role != null){
            doctor.setRole(role.getRoleName());
        }

        return doctor;
    }
}